package sm.codec;

import java.util.ArrayList;
import java.util.List;

import org.apache.mina.core.buffer.IoBuffer;

import sm.codec.api.Codec;
import sm.codec.api.CodecFactory;
import sm.codec.exception.DecodeException;
import sm.codec.exception.EncodeException;
import sm.codec.type.NullValue;
import sm.codec.type.Operator;
import sm.def.Type;

public class OperatorCodec extends NumberCodec implements Codec {

	@Override
	public Object decode(IoBuffer buffer) throws DecodeException {
		Object op = super.decode(buffer, Type.OPERATOR_TYPE);
		byte end = (byte) 0xA0;
		int curPos = buffer.position();
		if (op == null || op instanceof NullValue) {
			byte cur = buffer.get();
			if (cur != end) {
				buffer.position(curPos);
			}
			return op;
		} else {
			List<Object> objects = new ArrayList<Object>();
			byte cur = buffer.get();
			while (cur != end) {
				int fieldType = (cur & 0xFF) >>> 4;
				buffer.position(curPos);
				Object obj = CodecFactory.getCodec(fieldType).decode(buffer);
				objects.add(obj);
				curPos = buffer.position();
				cur = buffer.get();
			}
			int code = ((Double) op).intValue();
			return new Operator(code, objects);
		}

	}

	@Override
	public void encode(IoBuffer buffer, Object obj) throws EncodeException {
		if (obj == null || obj instanceof NullValue) {
			buffer.put((byte) 0xAF);
		} else {
			Operator expression = (Operator) obj;
			List<Object> operands = expression.getOperands();
			int op = expression.getOperator();
			super.encode(buffer, new Double(op), Type.OPERATOR_TYPE);
			for (Object operand : operands) {
				CodecFactory.getCodec(Type.getTypeNumber(operand)).encode(buffer,
						operand);
			}
			byte end = (byte) 0xA0;
			buffer.put((byte) end);
		}
	}

}
